﻿using System;
using System.Web;
using System.Collections.Generic;
using System.Web.Mvc;
using System.Web.Security;
using System.Web.Script.Serialization;
using System.Linq;

using MvcCms.Data;
using MvcCms.Service.Filters;
using MvcCms.Service.Code.Email;
using MvcCms.Service;
using MvcCms.Store.Web.ViewModels;
using MvcCms.Data.Entities;
using MvcCms.Service.Code.Encryption;
using MvcCms.Service.Code;

using MvcCms.Store.Service;
using MvcCms.Store.Web.Code;
using AutoMapper;
using MvcCms.Store.ViewModels;
using System.Linq.Expressions;
using MvcCms.Service.Cache;

namespace MvcCms.Store.Web.Controllers
{
    [RequireSsl(Redirect = true)]    
    public class CheckoutController : MvcCms.Service.Code.BaseClasses.CMSControllerBase
    {
        #region Constructors
        private readonly IStoreService _storeService;
        private readonly ICacheService _cacheService;
        private readonly ShoppingCart _shoppingCart;
        private readonly IAccountService _accountService;
        public CheckoutController(ICacheService cacheService, ShoppingCart shoppingCart, IStoreService storeService, IAccountService accountService, IZoneService zoneService, ICmsService cmsService)
            : base(cmsService, zoneService, accountService)
        {
            _storeService = storeService;
            _cacheService = cacheService;
            _shoppingCart = shoppingCart;
            _accountService = accountService;
        }
        #endregion

        public ActionResult CheckOutGuest()
        {
            var portal = _cacheService.GetCurrentPortal();
            ViewBag.CheckOutGuest = true;
            var cart = _shoppingCart.GetCart(this.HttpContext);

            if (Session["ShippingMethodRateID"] == null)
            {
                return RedirectToAction("index", "shoppingcart", null);
            }
            int shippingRateId = int.Parse(Session["ShippingMethodRateID"].ToString());
            var shippingRate = _storeService.GetShippingMethodRate(shippingRateId);
            var cartTotal = cart.GetTotal();
            var shippingTotal = 0m;
            if (shippingRate.Price.HasValue)
            {
                shippingTotal = decimal.Parse(shippingRate.Price.GetValueOrDefault().ToString());
            }
            else
            {
                shippingTotal = cartTotal * shippingRate.PercentOfTotal.GetValueOrDefault();
            }
            shippingRate.Price = shippingTotal;

            var paymentDataViewModel = new PaymentDataCCViewModel();
            var orderViewModel = new OrderViewModel();
            var cartModel = new ShoppingCartViewModel
            {
                CartItems = cart.GetCartItems(),
                CartTotal = cart.GetTotal()
            };
            orderViewModel.Total = cart.GetTotal() + shippingTotal;
            orderViewModel.ShippingMethodRate = shippingRate;

            var model = new DefaultViewModel
            {
                _Cart = cartModel,
                _PaymentDataCC = paymentDataViewModel,
                _Order = orderViewModel,
                _Portal = portal
            };
            ViewBag.Title = portal.Name;
            return View("AddressAndPayment", model);
        }

        [AuthorizeStore]
        public ActionResult AddressAndPayment()
        {
            var portal = _cacheService.GetCurrentPortal();
            var cart = _shoppingCart.GetCart(this.HttpContext);

            if (Session["ShippingMethodRateID"] == null)
            {
                return RedirectToAction("index", "shoppingcart", null);
            }
            int shippingRateId = int.Parse(Session["ShippingMethodRateID"].ToString());
            var shippingRate = _storeService.GetShippingMethodRate(shippingRateId);
            var cartTotal = cart.GetTotal();
            var shippingTotal = 0m;
            if (shippingRate.Price.HasValue)
            {
                shippingTotal = decimal.Parse(shippingRate.Price.GetValueOrDefault().ToString());
            }
            else
            {
                shippingTotal = cartTotal * shippingRate.PercentOfTotal.GetValueOrDefault();
            }
            shippingRate.Price = shippingTotal;

            ViewBag.CheckOutGuest = false;
            var user = _storeService.GetUserIncCC();

            var lastOrder = _storeService.GetOrder(user.UserID);
            
            if (lastOrder == null) { lastOrder = new StoreOrder(); }
            lastOrder.Total = cart.GetTotal() + shippingTotal;
            lastOrder.ShippingMethodRate = shippingRate;

            Mapper.CreateMap<StoreOrder, OrderViewModel>();
            var orderModel = Mapper.Map<StoreOrder, OrderViewModel>(lastOrder);
            
            var cartModel = new ShoppingCartViewModel
            {
                CartItems = cart.GetCartItems(),
                CartTotal = cart.GetTotal()
            };

            var model = new DefaultViewModel
            {                
                _Cart = cartModel,
                _Order = orderModel,
                _Portal = portal
            };
            ViewBag.Title = portal.Name;
            return View(model);
        }

        [HttpPost]
        public ActionResult AddressAndPayment([Bind(Prefix = "_Order")] OrderViewModel orderViewModel, [Bind(Prefix = "_PaymentDataCC")] PaymentDataCCViewModel paymentDataViewModel, bool? rememberPaymentData)
        {
            var portal = _cacheService.GetCurrentPortal();
            try
            {
                bool isGuestCheckOut = false;
                var user = _accountService.GetUser();
                if (user == null)
                {
                    isGuestCheckOut = true;                    
                    user = _accountService.GetUser(portal.URLAuthority + "_Guest");
                }
                ViewBag.CheckOutGuest = isGuestCheckOut;

                orderViewModel.UserID = user.UserID;
                orderViewModel.OrderDate = DateTime.Now;
                orderViewModel.PortalID = portal.PortalID;

                Mapper.CreateMap<OrderViewModel, StoreOrder>();
                var order = Mapper.Map<OrderViewModel, StoreOrder>(orderViewModel);

                var stateProvince = _cacheService.GetStateProvince(orderViewModel.State.ToUpper());
                if (stateProvince == null)
                {
                    var expression = GetExpressionText<DefaultViewModel, string>(
                        x => x._Order.State
                    );
                    ModelState.AddModelError(expression, "Could Not Find State");

                    var cartToReturn = _shoppingCart.GetCart(this.HttpContext);
                    var cartModel = new ShoppingCartViewModel
                    {
                        CartItems = cartToReturn.GetCartItems(),
                        CartTotal = cartToReturn.GetTotal()
                    };
                    orderViewModel.Total = cartModel.CartTotal;

                    var model = new DefaultViewModel
                    {
                        _Cart = cartModel,
                        _PaymentDataCC = paymentDataViewModel,
                        _Order = orderViewModel,
                        _Portal = portal
                    };
                    ViewBag.Title = portal.Name;
                    return View(model);
                }

                //Process the order
                var cart = _shoppingCart.GetCart(this.HttpContext);
                if (Session["ShippingMethodRateID"] == null)
                {
                    return RedirectToAction("index", "shoppingcart", null);
                }
                int shippingRateId = int.Parse(Session["ShippingMethodRateID"].ToString());
                var shippingRate = _storeService.GetShippingMethodRate(shippingRateId);
                order.ShippingRateID = shippingRateId;
                var cartTotal = cart.GetTotal();
                var shippingTotal = 0m;
                if (shippingRate.Price.HasValue)
                {
                    shippingTotal = decimal.Parse(shippingRate.Price.GetValueOrDefault().ToString());
                }
                else
                {
                    shippingTotal = cartTotal * shippingRate.PercentOfTotal.GetValueOrDefault();
                }
              
                if (!isGuestCheckOut)
                {
                    user = _storeService.GetUserIncCC();
                }

                var amount = Math.Round(cartTotal + shippingTotal, 2);
               
                //Save Order               
                cart.CreateOrder(order);


                return RedirectToAction("Complete", new { id = order.OrderID });                
            }
            catch(Exception ex)
            {
                MvcCmsEmails.DynamicEmail("ecom error", "support@mvccms.com", "jon@mvccms.com", ex.Message);
                portal = _cacheService.GetCurrentPortal();
                var cartToReturn = _shoppingCart.GetCart(this.HttpContext);
                var cartModel = new ShoppingCartViewModel
                {
                    CartItems = cartToReturn.GetCartItems(),
                    CartTotal = cartToReturn.GetTotal()
                };
                orderViewModel.Total = cartModel.CartTotal;

                var model = new DefaultViewModel
                {
                    _Cart = cartModel,
                    _PaymentDataCC = paymentDataViewModel,
                    _Order = orderViewModel,
                    _Portal = portal
                };             
                ViewBag.Title = portal.Name;
                return View(model);
            }
        }

        public static string GetExpressionText<TModel, TProperty>(Expression<Func<TModel, TProperty>> expression)
        {
            return ExpressionHelper.GetExpressionText(expression);
        }

        [AuthorizeStore]      
        public ActionResult TransactionError(string msg, Portal portal)
        {
            ViewBag.ErrorMessage = msg;
            var model = new DefaultViewModel
            {
                _Portal = portal
            };
            ViewData["PageTitle"] = "Transaction Error";
            return View("transactionerror", model);
        }

        public ActionResult Complete(int id)
        {
            var portal = _cacheService.GetCurrentPortal();

            var user = _accountService.GetUser();
            if (user == null)
            {
                user = _accountService.GetUser(portal.URLAuthority + "_Guest");
            }
            var order = _storeService.GetOrder(id, user.UserID);
            bool isValid = (order != null);

            if (isValid)
            {                
                Mapper.CreateMap<StoreOrder, OrderViewModel>();
                var orderViewModel = Mapper.Map<StoreOrder, OrderViewModel>(order);

                var model = new DefaultViewModel
                {
                    _Order = orderViewModel,
                    _Portal = portal
                };
                ViewBag.Title = portal.Name;
                return View(model);
            }
            else
            {
                return View("Error");
            }
        }
    }
}
